using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Caliburn.Micro;
using MediaOwl.Common;
using MediaOwl.Common.ScreenManagement;
using MediaOwl.Common.ViewModels;
using MediaOwl.Cryptos.Model;
using MediaOwl.Cryptos.Resources;
using MediaOwl.Cryptos.Services;

namespace MediaOwl.Cryptos.ViewModels
{
    [Export(typeof(IWorkitem<CryptosViewModel>))]
    public sealed class RijndaelChiffreViewModel : Workitem<CryptosViewModel>
    {
        #region Fields
        private readonly RijndaelChiffre chiffre;
        #endregion

        #region Constructor
        [ImportingConstructor]
        public RijndaelChiffreViewModel(RijndaelChiffre chiffre)
        {
            this.chiffre = chiffre;

            DisplayName = Captions.RijndaelChiffreTitle;
            IsHomeScreen = true;
            Order = 2;
            Description = Captions.RijndaelChiffreDescription;

            IvList = new BindableCollection<CryptValue<byte>>(chiffre.GetVector());
            KeyList = new BindableCollection<CryptValue<byte>>(chiffre.GetKey());

            crypt = true;
            textInput = Captions.DefaultTextInput;
        }
        #endregion

        #region Properties with Backing-Fields

        public string Description { get; private set; }

        private BindableCollection<CryptValue<byte>> ivList;
        public BindableCollection<CryptValue<byte>> IvList
        {
            get { return ivList; }
            set { ivList = value; NotifyOfPropertyChange(() => IvList);}
        }

        private BindableCollection<CryptValue<byte>> keyList;
        public BindableCollection<CryptValue<byte>> KeyList
        {
            get { return keyList; }
            set { keyList = value; NotifyOfPropertyChange(() => KeyList);}
        }

        private string textInput;
        public string TextInput
        {
            get { return textInput; }
            set
            {
                textInput = value;
                NotifyOfPropertyChange(() => TextInput);
            }
        }

        private string result;
        public string Result
        {
            get { return result; }
            set
            {
                result = value;
                NotifyOfPropertyChange(() => Result);
            }
        }

        private bool crypt;
        public bool Encrypt
        {
            get
            {
                return crypt;
            }
            set
            {
                crypt = value;
                NotifyOfPropertyChange(() => Encrypt);
                NotifyOfPropertyChange(() => Decrypt);
            }
        }
        public bool Decrypt
        {
            get { return !crypt; }
            set
            {
                crypt = !value;
                NotifyOfPropertyChange(() => Encrypt);
                NotifyOfPropertyChange(() => Decrypt);
            }
        }

        public bool CanExecute
        {
            get { return !string.IsNullOrEmpty(TextInput); }
        }

        public bool CanMoveInput
        {
            get { return !string.IsNullOrEmpty(Result); }
        }

        #endregion

        #region Methods
        
        public void Execute()
        {
            Result = crypt
                ? chiffre.Encrypt(textInput, KeyList.Select(x => x.Value).ToArray(), IvList.Select(x => x.Value).ToArray())
                : chiffre.Decrypt(textInput, KeyList.Select(x => x.Value).ToArray(), IvList.Select(x => x.Value).ToArray());

            NotifyOfPropertyChange(() => CanMoveInput);
        }

        public void MoveInput()
        {
            TextInput = Result;
            Result = string.Empty;
            NotifyOfPropertyChange(() => CanMoveInput);
        }

        public IEnumerable<IResult> ShowDescription()
        {
            yield return Show.Dialog<DialogMessageViewModel>()
                .Configured(x => x.WithData(Description, "Info"));
        }

        #endregion
    }
}